片段快取
================

片段快取指快取網頁某片段。例如，如果一個頁面在表中顯示每年的銷售總結，我們可以儲存此表在快取中，減少每次請求需要重新產生的時間。

要使用片段快取，在控制器視圖腳本中調用 [CController::beginCache()|CBaseController::beginCache()] 和 [CController::endCache()|CBaseController::endCache()] 。這兩種方法開始和結束包括的頁面內容將被快取。類似 [data caching](/doc/guide/caching.data) ，我們需要一個編號，識別被快取的片段。

~~~
[php]
...別的HTML內容...
<?php if($this->beginCache($id)) { ?>
...被快取的內容...
<?php $this->endCache(); } ?>
...別的HTML內容...
~~~

在上面的，如果 [beginCache()|CBaseController::beginCache()] 返回false，快取的內容將此地方自動插入; 否則，在 `if` 語句內的內容將被執行並在[ endCache()|CBaseController::endCache()] 觸發時快取。


快取選項
---------------

當調用 [beginCache()|CBaseController::beginCache()]，可以提供一個包含快取選項組成的陣列作為第二個參數，以自定片段快取。事實上，為了方便，[beginCache()|CBaseController::beginCache()] 和 [endCache()|CBaseController::endCache()] 是 [ COutputCache ] 小工具的包裝。因此 [COutputCache] 的所有屬性都可以在快取選項中初始化。

### 有效期

也許是最常見的選項是 [duration|COutputCache::duration]，指定了內容在快取中多久有效。和 [CCache::set()]過期參數有點類似。下面的程式碼快取內容片段最多一小時：

~~~
[php]
...其他 HTML 內容...
<?php if($this->beginCache($id, array('duration'=>3600))) { ?>
...被快取的內容...
<?php $this->endCache(); } ?>
...其他 HTML 內容...
~~~

如果我們不設定期限，它將預設為 60 ，這意味著 60 秒後快取內容將無效。

### 依賴性

像 [data caching](/doc/guide/caching.data) ，內容片段被快取也可以有依賴。例如，文章的內容被顯示取決於文章是否被修改。

要指定一個依賴，我們建立了 [dependency|COutputCache::dependency] 選項，可以是一個實現 [ICacheDependency]的物件或可用於產生依賴物件的配置陣列。下面的程式碼指定片段內容取決於 `lastModified` 的值是否變化：

~~~
[php]
...其他 HTML 內容...
<?php if($this->beginCache($id, array('dependency'=>array(
		'class'=>'system.caching.dependencies.CDbCacheDependency',
		'sql'=>'SELECT MAX(lastModified) FROM Post')))) { ?>
...被快取的內容...
<?php $this->endCache(); } ?>
...其他 HTML 內容...
~~~

### 變化

快取的內容可根據一些參數變化。例如，每個人的檔案都不一樣。快取的檔案內容將根據每個人 ID 變化。這意味著，當調用 [beginCache()|CBaseController::beginCache()] 時將用不同的ID。

[COutputCache] 內置了這一屬性，程式設計師不需要撰寫根據 ID 變動內容的模式。以下是總結。

   - [varyByRoute|COutputCache::varyByRoute]: 設置此選項為 true ，快取的內容將根據 [route](/doc/guide/basics.controller#route) 變化。因此，每個控制器和行動的組合將有一個單獨的快取內容。

   - [varyBySession|COutputCache::varyBySession]: 設置此選項為 true ，快取的內容將根據 session ID 變化。因此，每個使用者會話可能會看到由快取提供的不同內容。

   - [varyByParam|COutputCache::varyByParam]: 設置此選項的陣列裡的名字，快取的內容將根據 GET 參數的值變動。例如，如果一個頁面顯示文章的內容根據 `id` 的 GET 參數，我們可以指定 [varyByParam|COutputCache::varyByParam] 為 `array('id')`，以使我們能夠快取每篇文章內容。如果沒有這樣的變化，我們只能能夠快取某一文章。

   - [varyByExpression|COutputCache::varyByExpression]: 藉由設定一個 PHP 表達式給這個選項，我們可以使得快取的內容根據 PHP 表達式的結果而變動。

### 請求類型

有時候，我們希望片段快取只對某些類型的請求啟用。例如，對於某張網頁上顯示表單，我們只想要快取 initially requested 表單(通過GET請求)。任何隨後顯示（通過POST請求）的表單將不被快取，因為表單可能包含使用者輸入。要做到這一點，我們可以指定 [requestTypes|COutputCache::requestTypes] 選項：

~~~
[php]
...其他 HTML 內容...
<?php if($this->beginCache($id, array('requestTypes'=>array('GET')))) { ?>
...被快取的內容...
<?php $this->endCache(); } ?>
...其他 HTML 內容...
~~~

巢狀快取
--------------

片段快取可以巢狀。就是說一個快取片段附在一個更大的片段快取裡。例如，意見快取在內部片段快取，而且它們一起在外部快取中在文章內容裡快取。

~~~
[php]
...其他 HTML 內容...
<?php if($this->beginCache($id1)) { ?>
...外部被快取內容...
	<?php if($this->beginCache($id2)) { ?>
	...內部被快取內容...
	<?php $this->endCache(); } ?>
...外部被快取內容...
<?php $this->endCache(); } ?>
...其他 HTML 內容...
~~~

巢狀快取可以設定不同的快取選項。例如， 在上面的例子中內部快取和外部快取可以設置時間長短不同的持續值。當資料儲存在外部快取無效，內部快取仍然可以提供有效的內部片段。 然而，反之就不行了。如果外部快取包含有效的資料， 它會永遠保持快取副本，即使內容中的內部快取已經過期。

<div class="revision">$Id$</div>